package com.by.service.impl;

import com.by.bean.SProductEnquiry;
import com.by.bean.SupplierEnquiry;
import com.by.common.bean.PageBean;
import com.by.common.crud.BaseServiceImpl;
import com.by.common.utils.AssertUtils;
import com.by.common.utils.DateUtils;
import com.by.mapper.SProductEnquiryDetailMapper;
import com.by.mapper.SProductEnquiryMapper;
import com.by.mapper.SupplierEnquiryMapper;
import com.by.query.SupplierEnquiryQuery;
import com.by.query.SupplierProductEnquiryQuery;
import com.by.service.SProductEnquiryService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author Ye QS
 * @version 0.1
 * @className SProductEnquiryServiceImpl
 * @description
 * @date 2024/9/26 14:28
 * @since jdk11
 */
@Service
public class SProductEnquiryServiceImpl extends BaseServiceImpl<SProductEnquiry, SProductEnquiryMapper> implements SProductEnquiryService {
    final String PREFIX = "CPXJ";
    String maxCode = null;

    @Autowired
    SProductEnquiryDetailMapper sProductEnquiryDetailMapper;

    @Autowired
    SupplierEnquiryMapper supplierEnquiryMapper;
    @Override
    public Map queryDetail(int id) {
        return baseMapper.queryDetail(id);
    }
    /**
     * 分页查询供应商产品询价信息
     *
     * @param query 供应商产品询价的查询条件，包含分页信息和查询参数
     * @return 返回分页查询结果，包含总记录数、当前页数据等信息
     */
    @Override
    public PageBean querySupplierProductEnquiry(SupplierProductEnquiryQuery query) {
        // 开始分页，设置当前页和每页记录数
        PageHelper.startPage(query.getPage(), query.getPageSize());

        // 根据查询条件查询供应商产品询价信息
        List list = baseMapper.querySupplierProductEnquiry(query);

        // 创建PageInfo对象，用于封装分页相关数据
        PageInfo info = new PageInfo<>(list);

        // 创建并返回PageBean对象，包含分页信息和查询结果
        return new PageBean<>(query.getPage(), query.getPageSize(), info.getTotal(), list);
    }

    /**
     * 使用事务处理，确保产品询价单保存操作的原子性
     * 重写保存产品询价单的方法
     * @param entity 要保存的产品询价单实体对象
     * @return 返回保存结果，1表示成功
     * 本方法主要逻辑：
     * 1. 生成产品询价单代码
     * 2. 设置产品询价单代码到实体
     * 3. 调用父类保存方法，保存产品询价单
     * 4. 使用断言校验保存结果，确保产品询价单保存成功
     * 5. 若产品询价单包含详情列表，则批量保存详情
     * 6. 使用断言校验详情保存结果，确保产品询价明细保存成功
     * 7. 在供应商询价表中记录产品询价单ID和类别ID的关联
     * 本方法确保产品询价单及其详情的保存操作要么全部成功，要么全部失败，保障了数据的一致性
     */
    @Transactional
    @Override
    public int save(SProductEnquiry entity) {
        // 生成产品询价单代码
        generateCode();
        // 设置产品询价单代码到实体
        entity.setCode(maxCode);
        // 调用父类保存方法，保存产品询价单
        int rs = super.save(entity);
        // 使用断言校验保存结果，确保产品询价单保存成功
        AssertUtils.isNotSuccess(rs, "产品询价单保存失败");

        // 若产品询价单包含详情列表，则批量保存详情
        if (null != entity.getSProductEnquiryDetailList() && entity.getSProductEnquiryDetailList().size() > 0) {
            rs = sProductEnquiryDetailMapper.batchSave(entity.getId(), entity.getSProductEnquiryDetailList());
            // 使用断言校验详情保存结果，确保产品询价明细保存成功
            AssertUtils.isNotSuccess(rs, "产品询价明细保存失败");
        }

        // 在供应商询价表中记录产品询价单ID和类别ID的关联
        rs = supplierEnquiryMapper.save(entity.getId(), entity.getCategoryId());
        // 返回成功标识
        return 1;

    }

    /**
     * 生成代码序列号
     * 该方法用于根据当前日期和已有代码序列号生成一个新的代码序列号
     * 序列号的格式为：PREFIXYYYYMMDDSSS，其中YYYYMMDD为当前日期，SSS为序列号，从001开始递增
     *
     * @return 生成的代码序列号
     */
    String generateCode() {
        // 获取当前日期的年月日字符串
        String ym = DateUtils.getYmd();
        // 判断当前最大代码序列号是否为空
        if (null == maxCode) {
            // 如果为空，则从数据库查询当前日期的最大代码序列号
            maxCode = baseMapper.queryMaxCode(ym);
            // 判断查询结果是否为空
            if (null == maxCode) {
                // 如果查询结果为空，则将当前日期的序列号初始化为001
                maxCode = PREFIX + ym + "001";
                return maxCode; // 返回初始化后的序列号
            }
        }
        // 提取当前最大代码序列号中的年月部分
        String tmpYm = maxCode.substring(4, 10);
        // 判断当前最大代码序列号的年月部分是否与当前日期的年月部分相同
        if (!ym.equals(tmpYm)) {
            // 如果不相同，则将序列号重置为当前日期的001
            maxCode = PREFIX + ym + "001";
            return maxCode; // 返回重置后的序列号
        }
        // 提取当前最大代码序列号中的序列号部分
        String seq = maxCode.substring(10);
        // 将序列号部分转换为整数并加1
        int tmp = Integer.parseInt(seq);
        tmp++;
        // 生成新的代码序列号
        maxCode = PREFIX + ym + String.format("%03d", tmp);
        return maxCode; // 返回新的代码序列号
    }
}
